from django.contrib.auth import get_user_model
from django_redis import get_redis_connection

User = get_user_model()


class BackendBase:
    def get_user(self, pk):
        try:
            return User.objects.get(pk=pk)
        except User.DoesNotExist:
            return None

    def user_can_authenticate(self, user):
        # 表示用户是否可以登录，在一些场景中有一些用户已经被锁定或者已经删除，都是不允许登录
        if hasattr(user, 'can_authenticate'):
            return user.can_authenticate()

        return user.is_active and user.is_delete


class SmsCodeBackend(BackendBase):
    """
    验证码登录
    """
    def authenticate(self, request, identity, method, code, **kwargs):
        if method != 'code':
            return None

        conn = get_redis_connection('sms_code')
        sms_code = conn.get(identity)
        if sms_code is None:
            raise Exception('验证码错误')

        if sms_code.decode('utf-8') != code:
            raise Exception('验证码错误')

        try:
            user = User.objects.get(phone=identity, phone_validated=True)

            if not self.user_can_authenticate(user):
                raise Exception('用户已经锁定或者被删除，请联系管理员！！！')

            return user
        except User.DoesNotExist:
            raise Exception('账号不存在')


class PasswordBackend(BackendBase):
    """
    密码登录
    """
    def authenticate(self, request, identity, method, password, **kwargs):
        if method != 'password':
            return None

        try:
            user = User.objects.get(username=identity)

            if not user.check_password(password):
                raise Exception('密码错误！！')

            if not self.user_can_authenticate(user):
                raise Exception('用户已经锁定或者被删除，请联系管理员！！！')

            return user
        except User.DoesNotExist:
            raise Exception('账号不存在')
